// Learn TypeScript:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/2.4/manual/en/scripting/life-cycle-callbacks.html

import { MeshTools } from "../meshTools/MeshTools";
import { Publish } from "../meshTools/tools/Publish";
import { MoveType, RoomType } from "./bean/EnumBean";
import { AcceptInvite, IllegalOperation, InviteKickOut, MoveBlockFail, NoticeLeaveInvite, NoticeMoveBlock, NoticeScoreChg, NoticeSettlement, NoticeStartGame, NoticeUserInviteStatus, ObstacleBlock, UserInfo, GameFrameData } from "./bean/GameBean";
import { GlobalBean } from "./bean/GlobalBean";
import LanguageType from "./bean/LanguageType";
import { EventType } from "./common/EventCenter";
import { GameMgr } from "./common/GameMgr";
import GamePageController from "./game/GamePageController";
import { BlockAnimationManager } from "./game/BlockAnimationManager";
import HallPageController, { HallOrMatch } from "./hall/HallPageController";
import TopUpDialogController from "./hall/TopUpDialogController";
import { ErrorCode } from "./net/ErrorCode";
import { GameServerUrl } from "./net/GameServerUrl";
import { HttpManager } from "./net/HttpManager";
import { AutoMessageBean, AutoMessageId, ReceivedMessageBean } from "./net/MessageBaseBean";
import { MessageId } from "./net/MessageId";
import { WebSocketManager } from "./net/WebSocketManager";
import { WebSocketTool } from "./net/WebSocketTool";
import StartUpPageController from "./start_up/StartUpPageController";
import TipsDialogController from "./TipsDialogController";
import ToastController from "./ToastController";
import { AudioMgr } from "./util/AudioMgr";
import { Config } from "./util/Config";
import { AudioManager } from "./util/AudioManager";

const { ccclass, property } = cc._decorator;

window.languageName = "en";

export enum PageType {
    START_UP_PAGE,//启动页面
    HALL_PAGE,//大厅页面
    GAME_PAGE,//游戏页面
}

@ccclass
export default class GlobalManagerController extends cc.Component {

    // 全局单例，便于其他脚本安全获取
    public static Instance: GlobalManagerController = null;

    @property(TipsDialogController)
    tipsDialogController: TipsDialogController = null //这个是错误弹窗 只有一个退出按钮
    @property(TopUpDialogController)
    topUpDialogController: TopUpDialogController = null //充值弹窗
    @property(cc.Node)
    netError: cc.Node = null  //这个是断网的时候展示的转圈的
    @property(ToastController)
    toastController: ToastController = null  //toast 的布局

    @property(cc.Node)
    startUpPage: cc.Node = null  //启动页
    @property(cc.Node)
    hallPage: cc.Node = null  //大厅页
    @property(cc.Node)
    gamePage: cc.Node = null  //游戏页面



    currentPage: PageType = PageType.START_UP_PAGE //当前展示的页面，默认展示的是启动页面

    startUpPageController: StartUpPageController = null  //启动页面的总管理器
    hallPageController: HallPageController = null   //大厅页面的总管理器
    gamePageController: GamePageController = null   //游戏页面的总管理器


    onLoad() {
        // 建立单例引用
        GlobalManagerController.Instance = this;
        cc.resources.preloadDir(Config.hallRes, cc.SpriteFrame);//提前预加载大厅图片资源

        // 获取音频管理器实例
        const audioMgr = AudioMgr.ins;
        // 初始化音频管理器（如果还未初始化）
        audioMgr.init();

        cc.debug.setDisplayStats(false);
        //获取URL拼接渠道参数
        this.getUrlParams();
        GameMgr.H5SDK.AddAPPEvent();

        this.getAppConfig();

        cc.game.on(cc.game.EVENT_SHOW, () => {
            GameMgr.Console.Log("EVENT_SHOW")
            GameMgr.GameData.GameIsInFront = true;
            // 触发重连
            WebSocketTool.GetInstance().atOnceReconnect();
            setTimeout(() => {
                AudioManager.playBgm()
            }, 200)

        }, this);

        cc.game.on(cc.game.EVENT_HIDE, () => {
            GameMgr.Console.Log("EVENT_HIDE")
            GameMgr.GameData.GameIsInFront = false;
            // 页面隐藏时立即停止发送帧输入
            if (this.gamePageController) {
                console.log('[GlobalManagerController] 页面隐藏时立即停止发送帧输入');
                this.gamePageController.stopFrameInputImmediately();
            }
            // 断开WebSocket连接
            WebSocketTool.GetInstance().disconnect();
            this.netError.active = true
            AudioManager.stopBgm()

        }, this);

        //这里监听程序内消息
        GameMgr.Event.AddEventListener(EventType.AutoMessage, this.onAutoMessage, this);
        //这里监听长链接消息（异常）
        GameMgr.Event.AddEventListener(EventType.ReceiveErrorMessage, this.onErrorMessage, this);
        //这里监听长链接消息（正常）
        GameMgr.Event.AddEventListener(EventType.ReceiveMessage, this.onMessage, this);

        this.setCurrentPage(PageType.START_UP_PAGE)
        this.startUpPageController = this.startUpPage.getComponent(StartUpPageController)
        this.hallPageController = this.hallPage.getComponent(HallPageController)
        this.gamePageController = this.gamePage.getComponent(GamePageController)

    }

    /**
     * 根据地图类型设置背景图片（只设置背景，不设置方块皮肤）
     * mapType: 1 -> bg1/bg_up1/bg_down1
     *           2 -> bg2/bg_up2/bg_down2
     */
    public setMapBackground(mapType: number): void {
        const suffix = mapType === 2 ? '2' : '1';
        const bgPath = `bg/bg${suffix}`;
        const bgUpPath = `bg/bg_up${suffix}`;
        const bgDownPath = `bg/bg_down${suffix}`;

        // 直接设置背景图片
        this.setBackgroundSprite('game_bg', bgPath);
        this.setBackgroundSprite('bg_up', bgUpPath);
        this.setBackgroundSprite('bg_down', bgDownPath);


    }

    /**
     * 根据地图类型设置方块皮肤（在方块创建后调用）
     * mapType: 1 -> zhuankuai1
     *           2 -> zhuankuai2
     */
    public setBlockSkin(mapType: number): void {
        const suffix = mapType === 2 ? '2' : '1';
        const blockSkin = `zhuankuai${suffix}`;



        // 切换方块皮肤
        try {
            const mgr = BlockAnimationManager.getInstance();
            if (mgr && typeof (mgr as any).setBlockSkin === 'function') {
                (mgr as any).setBlockSkin(blockSkin);

            } else {
                console.warn('BlockAnimationManager 未初始化或 setBlockSkin 方法不存在');
            }
        } catch (e) {
            console.warn('切换方块皮肤失败:', e);
        }
    }

    /**
     * 重置时清空背景图片
     */
    public clearMapBackground(): void {


        const backgroundNodes = ['game_bg', 'bg_up', 'bg_down'];
        backgroundNodes.forEach(nodeName => {
            const root = cc.find('Canvas') || this.node;
            const node = this.findNodeByNameDeep(root, nodeName);
            if (node) {
                const sprite = node.getComponent(cc.Sprite);
                if (sprite) {
                    sprite.spriteFrame = null;
                }
            }
        });


    }

    /**
     * 直接设置背景图片（同步方式）
     */
    private setBackgroundSprite(nodeName: string, resPath: string): void {
        cc.resources.load(resPath, cc.SpriteFrame, (err, spriteFrame: cc.SpriteFrame) => {
            if (err) {
                console.warn(`加载背景失败: ${resPath}`, err);
                return;
            }
            const root = cc.find('Canvas') || this.node;
            const node = this.findNodeByNameDeep(root, nodeName);
            if (!node) {
                console.warn(`未找到背景节点: ${nodeName}`);
                return;
            }
            const sprite = node.getComponent(cc.Sprite) || node.addComponent(cc.Sprite);
            sprite.spriteFrame = spriteFrame;
        });
    }


    /**
     * 递归查找节点
     */
    private findNodeByNameDeep(root: cc.Node, name: string): cc.Node | null {
        if (!root) return null;
        if (root.name === name) return root;
        for (const child of root.children) {
            const found = this.findNodeByNameDeep(child, name);
            if (found) return found;
        }
        return null;
    }
    protected onEnable(): void {

    }

    protected onDestroy(): void {
        GameMgr.Event.RemoveEventListener(EventType.AutoMessage, this.onAutoMessage, this);
        GameMgr.Event.RemoveEventListener(EventType.ReceiveErrorMessage, this.onErrorMessage, this);
        GameMgr.Event.RemoveEventListener(EventType.ReceiveMessage, this.onMessage, this);
        // 释放单例引用
        if (GlobalManagerController.Instance === this) {
            GlobalManagerController.Instance = null;
        }
    }

    public getAppConfig(): void {
        GameMgr.H5SDK.GetConfig((config: any) => {
            MeshTools.Publish.appChannel = String(config.appChannel);
            MeshTools.Publish.appId = parseInt(config.appId);
            MeshTools.Publish.gameMode = String(config.gameMode);
            MeshTools.Publish.roomId = String(config.roomId) ?? "";
            MeshTools.Publish.currencyIcon = config?.gameConfig?.currencyIcon ?? "";

            MeshTools.Publish.code = encodeURIComponent(config.code);
            MeshTools.Publish.userId = String(config.userId);
            MeshTools.Publish.language = String(config.language);

            MeshTools.Publish.gsp = config.gsp == undefined ? 101 : parseInt(config.gsp);
            this.getHpptPath();

        });
    }

    getHpptPath() {
        this.setLanguage() //先设置语言
        if (!window.navigator.onLine) {
            this.showTips(window.getLocalizedStr('NetworkError'))
        } else {
            // 获取游戏服务器地址
            HttpManager.Instance.ReqServerUrl(() => {
                let httpUrl: string = GameServerUrl.Http;
                let wsUrl: string = GameServerUrl.Ws;
                if (httpUrl != "" || wsUrl != "") {
                    WebSocketManager.GetInstance().connect();
                }
            });

            // GameServerUrl.Ws = "ws://192.168.0.12:2069/acceptor"
            // WebSocketManager.GetInstance().connect();
        }
    }

    public getUrlParams(): void {
        let params: any = GameMgr.Utils.GetUrlParams(window.location.href);//获取当前页面的 url
        if (JSON.stringify(params) != "{}") {
            //@ts-ignore
            if (params.appChannel) {
                //@ts-ignore
                MeshTools.Publish.appChannel = params.appChannel;
                if (params.isDataByUrl) {
                    if (params.isDataByUrl === "true") {
                        MeshTools.Publish.appId = parseInt(params.appId);
                        MeshTools.Publish.gameMode = params.gameMode;
                        MeshTools.Publish.userId = params.userId;
                        MeshTools.Publish.code = params.code;
                        if (params.language) {
                            MeshTools.Publish.language = params.language;
                        }
                        if (params.roomId) {
                            MeshTools.Publish.roomId = params.roomId;
                        }
                        if (params.gsp) {
                            MeshTools.Publish.gsp = parseInt(params.gsp);
                        }
                        MeshTools.Publish.isDataByURL = true;
                    }
                }
            }
        }
    }

    setLanguage() {

        switch (Publish.GetInstance().language) {
            case LanguageType.SimplifiedChinese: //简体中文
                window.languageName = LanguageType.SimplifiedChinese_type
                break;
            case LanguageType.TraditionalChinese: //繁体中文
                window.languageName = LanguageType.TraditionalChinese_type
                break;
            default: //默认是英语
                window.languageName = LanguageType.English_type
                break
        }

        window.refreshAllLocalizedComp()
    }

    showTips(content: string) {

        this.tipsDialogController.showDialog(content, () => {
            GameMgr.H5SDK.CloseWebView()

        })
    }


    //程序内的通知消息
    onAutoMessage(autoMessageBean: AutoMessageBean) {
        switch (autoMessageBean.msgId) {

            case AutoMessageId.JumpHallPage://跳转进大厅页面
                this.setCurrentPage(PageType.HALL_PAGE)
                if (autoMessageBean.data.type === 1) { //1是启动页面跳转的 ，2 是玩家主动离开游戏房间
                    this.hallPageController.LoginSuccess()//因为初始进来的时候是启动页面，大厅页面是隐藏状态，下面发送的消息收不到，所以需要主动调用一次
                }
                break;
            case AutoMessageId.ReconnectionFailureMsg://长链接重连失败
                this.netError.active = false
                this.showTips(window.getLocalizedStr('NetworkError'))
                break;
            case AutoMessageId.LinkExceptionMsg://长链接异常
                this.netError.active = true
                // 断线时立即停止发送帧输入，避免重连前继续发送无效帧
                if (this.gamePageController) {
                    this.gamePageController.stopFrameInputImmediately();
                }
                break;
            case AutoMessageId.GameRouteNotFoundMsg://游戏线路异常的通知
                this.showTips(autoMessageBean.data.code)
                break;

            case AutoMessageId.SwitchGameSceneMsg://切换游戏场景
                this.setCurrentPage(PageType.GAME_PAGE)
                break;
            case AutoMessageId.WalletUpdateMsg://更新金豆余额的通知
                //发送获取更新用户信息的消息
                WebSocketManager.GetInstance().sendMsg(MessageId.MsgTypeUserInfo, {});
                break;
            case AutoMessageId.ServerCodeUpdateMsg://更新 code 的通知
                Publish.GetInstance().code = autoMessageBean.data.code
                break;

        }

    }

    //长链接消息(异常)
    onErrorMessage(messageBean: ReceivedMessageBean) {
        switch (messageBean.code) {
            case ErrorCode.ErrInvalidInviteCode://无效的邀请码
                this.hallPageController.joinError()
                break;
            case ErrorCode.ErrRequestUser://获取用户信息失败
                this.showTips(window.getLocalizedStr('GetUserInfoFailed'))
                // 断开WebSocket连接
                WebSocketTool.GetInstance().disconnect();

                break;
            case ErrorCode.ErrNotFoundRoom://没有找到指定的房间
                if (messageBean.msgId != MessageId.MsgTypeMoveBlock) {
                    this.toastController.showContent(window.getLocalizedStr('RoomDoesNotExist'))
                    //没有找到房间 就直接返回到大厅页面
                    this.setCurrentPage(PageType.HALL_PAGE)
                }

                break;
            case ErrorCode.ErrNotFoundUser:// 没有找到玩家信息
                if (messageBean.msgId === MessageId.MsgTypeEnterRoom) {//只有在这个messageId下 才会踢出到大厅
                    //没有找到玩家信息 就直接返回到大厅页面
                    this.setCurrentPage(PageType.HALL_PAGE)
                }
                break
            case ErrorCode.ErrEnoughUser://房间已满
                this.toastController.showContent(window.getLocalizedStr('RoomIsFull'))
                break;
            case ErrorCode.ErrChangeBalance://扣除金币失败
            case ErrorCode.ErrNotEnoughCoin://金币不足
                this.topUpDialogController.show(() => { })
                break;
            case ErrorCode.ErrPlaying://玩家已经在游戏中了
                //执行一遍 enterroom
                WebSocketManager.GetInstance().sendMsg(MessageId.MsgTypeEnterRoom, {})//重连进来的 玩家请求进入房间
                break

        }

    }

    //长链接消息(正常)
    onMessage(messageBean: ReceivedMessageBean) {
        switch (messageBean.msgId) {
            case MessageId.MsgTypeCreateWs://创建ws连接 成功  
                this.netError.active = false
                //登录
                WebSocketManager.GetInstance().sendMsg(MessageId.MsgTypeLogin, {});
                break;
            case MessageId.MsgTypeLogin://获取登录数据并存储
                GlobalBean.GetInstance().loginData = messageBean.data;
                if (this.currentPage === PageType.START_UP_PAGE) {
                    //判断当前是否是在启动页面
                    this.startUpPageController.setLogin()
                } else {
                    this.hallPageController.updateGold()
                    this.hallPageController.LoginSuccess()
                    //没有在游戏中，但是还停留在游戏页面
                    if (GlobalBean.GetInstance().loginData.roomId === 0 && this.currentPage === PageType.GAME_PAGE) {
                        this.setCurrentPage(PageType.HALL_PAGE) //返回到大厅
                    }
                }

                break;
            case MessageId.MsgTypePairRequest: //开始匹配
                this.hallPageController.setHallOrMatch(HallOrMatch.MATCH_PARENT)
                this.hallPageController.createMatchView();
                break
            case MessageId.MsgTypeCancelPair: //取消匹配
                this.hallPageController.setHallOrMatch(HallOrMatch.HALL_PARENT)
                break
            case MessageId.MsgTypeGameStart: //游戏开始
                // 检查是否是砖块派对游戏的GameStart消息


                // 原有的NoticeStartGame消息
                let noticeStartGame: NoticeStartGame = messageBean.data
                GlobalBean.GetInstance().noticeStartGame = noticeStartGame //存储游戏数据


                const index = GlobalBean.GetInstance().noticeStartGame.users.findIndex((item) => item.userId === GlobalBean.GetInstance().loginData.userInfo.userId);//搜索 
                //把游戏开始之后最新的金币余额进行赋值
                if (index != -1) {
                    GlobalBean.GetInstance().loginData.userInfo.coin = noticeStartGame.users[index].coin
                }
                // 延迟调用GameStart处理，确保页面已经激活
                this.scheduleOnce(() => {
                    // 根据mapType设置背景图片
                    this.setMapBackground(noticeStartGame.mapType);

                    // 初始化游戏内容
                    if (this.gamePageController) {
                        this.gamePageController.handleGameStart();
                        // 倒计时交由帧事件(eventType:1)统一驱动，避免与GameStart重复触发
                    }
                }, 0.1);

                if (noticeStartGame.roomType === RoomType.RoomTypeCommon) {// 房间类型 1-普通场 2-私人场
                    this.hallPageController.setGameData()
                } else {
                    this.setCurrentPage(PageType.GAME_PAGE) //开始游戏进入游戏页面
                }

                break

            case MessageId.MsgTypeEnterRoom://重连的游戏数据
                let enterRoomData = messageBean.data;

                // 如果服务端告知 gameStatus == 6，表示本局已结束：不进行断线重连，直接返回大厅
                if (enterRoomData && enterRoomData.gameStatus === 6) {

                    try {
                        // 清理游戏相关全局数据与视觉背景
                        GlobalBean.GetInstance().cleanData && GlobalBean.GetInstance().cleanData();
                        this.clearMapBackground();
                    } catch (e) {
                        console.warn("在处理 gameStatus=6 返回大厅时清理异常:", e);
                    }
                    this.setCurrentPage(PageType.HALL_PAGE);
                    break;
                }

                // 判断是否为断线重连（roomId > 0）
                if (enterRoomData && enterRoomData.roomId && enterRoomData.roomId > 0) {

                    // 🎯 处理并存储重连数据到GlobalBean（不要提前赋值原始数据，避免使用未处理的坐标）
                    // 同步补充砖块派对的数据，供结算页等模块使用
                    try {
                        const users = enterRoomData.users || [];
                        const playerData = users.map((u: any) => {
                            // 🎯 处理坐标：如果是(0,0)中心点，转换为NaN让客户端使用保底位置
                            let x = (typeof u.x === 'number') ? u.x : Number.NaN;
                            let y = (typeof u.y === 'number') ? u.y : Number.NaN;
                            
                            // 检测是否为中心点(0,0)，如果是则使用NaN触发保底逻辑
                            const isCenter = !Number.isNaN(x) && !Number.isNaN(y) && Math.abs(x) < 1e-3 && Math.abs(y) < 1e-3;
                            if (isCenter) {
                                console.warn(`[EnterRoom] 检测到中心点坐标(0,0)，转换为NaN使用保底位置 userId=${u.userId}, playerNumber=${u.playerNumber || u.pos || 1}`);
                                x = Number.NaN;
                                y = Number.NaN;
                            }
                            
                            return {
                                userId: u.userId,
                                playerNumber: u.playerNumber || u.pos || 1,
                                // 避免将缺失坐标默认为0（地图中心）。使用 NaN 作为占位，后续由客户端安全回退。
                                x: x,
                                y: y,
                                playerType: u.playerType || 'red',
                                surviveTime: u.surviveTime || 0,
                                rank: u.rank || 0,
                                nickName: u.nickName || u.nick_name || '',
                                avatar: u.avatar || '',
                                coin: typeof u.coin === 'number' ? u.coin : undefined,
                                bpStatus: u.bpStatus
                            };
                        });

                        GlobalBean.GetInstance().noticeStartGame = {
                            roomId: enterRoomData.roomId || 0,
                            roomType: enterRoomData.roomType || 1,
                            playerNum: enterRoomData.playerNum || (Array.isArray(users) ? users.length : 0),
                            mapType: enterRoomData.mapType || 1,
                            fee: enterRoomData.fee || 0,
                            users: playerData,
                            gameStatus: enterRoomData.gameStatus || 1,
                            countDown: enterRoomData.countDown || 0,
                        } as any;
                        
                        // 🔍 调试：验证处理后的玩家坐标
                        console.log(`[EnterRoom] 处理后的玩家数据:`, playerData.map(p => ({
                            userId: p.userId,
                            playerNumber: p.playerNumber,
                            x: p.x,
                            y: p.y
                        })));
                    } catch (e) {
                        console.warn('断线重连时构建数据失败:', e);
                    }

                    // 跳转到游戏页面
                    this.setCurrentPage(PageType.GAME_PAGE);

                    // 延迟调用断线重连逻辑，确保页面已经切换完成
                    this.scheduleOnce(() => {
                        if (this.gamePageController) {
                            this.gamePageController.handleReconnection(enterRoomData);
                        } else {
                            console.error("❌ gamePageController未设置，无法处理断线重连");
                        }
                    }, 0.1); // 延迟100ms确保页面切换完成
                } else {
                    // 正常的EnterRoom处理（非断线重连）
                    let noticeStartGame2: NoticeStartGame = enterRoomData;
                    GlobalBean.GetInstance().noticeStartGame = noticeStartGame2;
                    this.setCurrentPage(PageType.GAME_PAGE);
                }
                break;
            case MessageId.MsgTypeLeaveRoom:// 玩家主动离开房间
                let inviteLeve: InviteKickOut = messageBean.data;
                if (inviteLeve.userId === GlobalBean.GetInstance().loginData.userInfo.userId) {
                    GlobalBean.GetInstance().cleanData() //清空数据
                    let autoMessageBean: AutoMessageBean = {
                        'msgId': AutoMessageId.JumpHallPage,//进入大厅的消息
                        'data': { 'type': 2 } //2 是玩家主动离开游戏房间
                    }
                    GameMgr.Event.Send(EventType.AutoMessage, autoMessageBean);
                }
                break;
            case MessageId.MsgTypeCreateInvite://创建邀请（也就是创建私人游戏房间）
                GlobalBean.GetInstance().inviteInfo = messageBean.data;
                //点击 create 的回调
                this.hallPageController.joinCreateRoom()
                break
            case MessageId.MsgTypeAcceptInvite://接受邀请
                let acceptInvite: AcceptInvite = messageBean.data
                GlobalBean.GetInstance().inviteInfo = acceptInvite.inviteInfo;
                this.hallPageController.setAcceptInvite(acceptInvite)
                break
            case MessageId.MsgTypeLeaveInvite://收到离开房间的信息
                let noticeLeaveInvite: NoticeLeaveInvite = messageBean.data;
                this.hallPageController.leaveRoom(noticeLeaveInvite)
                break
            case MessageId.MsgTypeInviteReady://收到有玩家准备的消息
                let noticeUserInviteStatus: NoticeUserInviteStatus = messageBean.data;
                this.hallPageController.setReadyState(noticeUserInviteStatus)
                break
            case MessageId.MsgTypeNoticeInviteStatus://广播邀请状态
                let noticeUserInviteStatus2: NoticeUserInviteStatus = messageBean.data;
                this.hallPageController.setReadyState(noticeUserInviteStatus2)
                break;
            case MessageId.MsgTypeInviteKickOut://收到玩家被踢出的信息
                let inviteKickOut: InviteKickOut = messageBean.data;

                if (inviteKickOut.userId === GlobalBean.GetInstance().loginData.userInfo.userId) {
                    this.toastController.showContent(window.getLocalizedStr('kickout1'))
                    //被踢的是自己的话 直接返回大厅
                    this.setCurrentPage(PageType.HALL_PAGE)
                } else {
                    //这里拼接一下数据 走离开房间流程，其实是踢出房间
                    let noticeLeaveInvite1 = { 'userId': inviteKickOut.userId, 'isCreator': false }
                    this.hallPageController.leaveRoom(noticeLeaveInvite1)
                }
                break;
            case MessageId.MsgTypeUserInfo://更新用户信息的消息
                let userInfo: UserInfo = messageBean.data;
                GlobalBean.GetInstance().loginData.userInfo = userInfo
                this.hallPageController.updateGold()
                break;


            case MessageId.MsgTypeSettlement: //大结算
                let noticeSettlement: NoticeSettlement = messageBean.data
                this.gamePageController.setCongratsDialog(noticeSettlement)
                break

            case MessageId.MsgTypeGameFrame: // 游戏帧数据广播
                let gameFrameData: GameFrameData = messageBean.data;
                // 将帧数据传递给游戏页面控制器处理
                if (this.gamePageController) {
                    this.gamePageController.handleGameFrame(gameFrameData);
                }
                break

            // 注意：GameStart消息已在上面统一处理，这里的重复代码已移除


        }
    }

    //设置展示页面的
    setCurrentPage(pageType: PageType) {
        this.currentPage = pageType
        this.startUpPage.active = false
        this.hallPage.active = false
        this.gamePage.active = false

        switch (pageType) {
            case PageType.START_UP_PAGE:
                this.startUpPage.active = true
                break
            case PageType.HALL_PAGE:
                this.hallPage.active = true
                break
            case PageType.GAME_PAGE:
                this.gamePage.active = true
                break
        }

    }

    // update (dt) {}
}

// 提供便捷的静态获取方法
export function getGlobalManager(): GlobalManagerController | null {
    if (GlobalManagerController.Instance) return GlobalManagerController.Instance;
    // 兜底：尝试从场景中查找（Canvas 优先）
    const canvas = cc.find('Canvas');
    if (canvas) {
        const comp = canvas.getComponentInChildren('GlobalManagerController') as any;
        if (comp) {
            GlobalManagerController.Instance = comp;
            return comp;
        }
    }
    const scene = cc.director.getScene();
    if (scene) {
        for (const node of scene.children) {
            const comp = node.getComponent('GlobalManagerController') as any;
            if (comp) {
                GlobalManagerController.Instance = comp;
                return comp;
            }
        }
    }
    return null;
}

if (!CC_EDITOR) {
    cc.Sprite.prototype["onLoad"] = function () {
        this.srcBlendFactor = cc.macro.BlendFactor.ONE;
        this.dstBlendFactor = cc.macro.BlendFactor.ONE_MINUS_SRC_ALPHA;

        // 确保 spriteFrame 和其纹理存在
        if (this.spriteFrame && this.spriteFrame.getTexture()) {
            this.spriteFrame.getTexture().setPremultiplyAlpha(true);
        } else {
            console.warn("SpriteFrame or Texture is null");
        }
    }

    cc.Label.prototype["onLoad"] = function () {
        this.srcBlendFactor = cc.macro.BlendFactor.ONE;
        this.dstBlendFactor = cc.macro.BlendFactor.ONE_MINUS_SRC_ALPHA;
    }
    cc.macro.ALLOW_IMAGE_BITMAP = false;// 禁用 Bitmap 图片格式
}